package com.k8.rpc.util;

import com.alibaba.fastjson2.JSON;
import com.k8.common.util.ObjectUtil;
import com.k8.common.util.StrUtil;
import com.k8.rpc.config.ProtocolConfig;
import com.k8.rpc.metadata.ProtocolMetadata;
import com.k8.rpc.metadata.AppMetaData;
import com.k8.rpc.url.URL;
import com.k8.rpc.url.URLAddress;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import static com.k8.common.constants.CommonKeyConstants.METHODS_KEY;
import static com.k8.common.constants.CommonKeyConstants.PROVIDER;

public class URLUtils {
    private static String split = "#";

    public static void setMethods(URL url, List<Method> methods) {
        Map<String, String[]> tableMap = new TreeMap<>();
        for (Method method : methods) {
            Parameter[] parameters = method.getParameters();
            String[] paras = new String[parameters.length];
            int index = 0;
            for (Parameter parameter : parameters) {
                paras[index++] = parameter.getType().getName();
            }
            tableMap.put(method.getName(), paras);
        }
        String methodS = JSON.toJSONString(tableMap);
        url.setParameter(METHODS_KEY, methodS);
    }

    public static String getFullPath(URL url) {
        if (StrUtil.isNotEmpty(url.getCacheURLKey())) return url.getCacheURLKey();
        //path一般由interface::version构成
        String key = url.getProtocol() + "://" + url.getIp() + ":" + url.getPort() + url.getPath();
        url.setCacheURLKey(key);
        return key;
    }

    public static URL copy(URL oldUrl) {
        URL url = new URL();
        Map<String, String> oldUrlParams = oldUrl.getUrlParams();
        oldUrlParams.forEach((key, value) -> {
            url.setParameter(key, value);
        });
        URLAddress oldAddress = oldUrl.getAddress();
        URLAddress address = url.getAddress();
        address.setHost(oldAddress.getHost());
        address.setPath(oldAddress.getPath());
        address.setPort(oldAddress.getPort());
        Map<String, Object> attributes = oldUrl.getAttributes();
        if (attributes != null) {
            attributes.forEach((key, value) -> {
                url.putAttribute(key, value);
            });
        }
        Map<String, String> urlParams = oldUrl.getUrlParams();
        urlParams.forEach((key, value) -> {
            url.setParameter(key, value);
        });
        url.setSystemConfigUrl(oldUrl.getSystemConfigUrl());
        url.setSystem_first(false);
        return url;
    }

    public static String getIp(String host) {
        if (host == null) throw new IllegalArgumentException("Host is null");
        try {
            InetAddress inetAddress = InetAddress.getByName(host);
            return inetAddress.getHostAddress();
        } catch (UnknownHostException e) {
            try {
                return InetAddress.getLocalHost().getHostAddress();
            } catch (UnknownHostException ex) {
                throw new IllegalStateException("Can not resolve host to ip,host:" + host);
            }
        }
    }

    public static String buildURLString(URL url) {
        String result = buildURLSimpleString(url);
        Map<String, String> urlParams = url.getUrlParams();
        Set<String> keys = urlParams.keySet();
        for (String key : keys) {
            result = result + key + "=" + urlParams.get(key) + "&";
        }
        if (keys.size() > 0) {
            result = result.substring(0, result.length() - 1);
        }
        return result;
    }

    public static String buildURLSimpleString(URL url) {
        return url.getProtocol() + "://"
                + url.getIp() + ":"
                + url.getPort()
                + url.getPath();
    }

    public static URL copySimpleUrl(URL originUrl) {
        ObjectUtil.checkNotNull(originUrl, "URL is null");
        URL url = new URL();
        url.setProtocol(originUrl.getProtocol());
        url.setHost(originUrl.getHost());
        url.setPort(originUrl.getPort());
        url.setPath(originUrl.getPath());
        return url;
    }

    public static URL buildSystemURL() {
        URL systemURL = new URL();
        System.getProperties().forEach((keyObj, valueObj) -> {
            String key = keyObj.toString();
            String value = valueObj.toString();
            // 筛选以 "config." 开头的参数（按需修改前缀）
            if (key.startsWith("k8.config.")) {
                systemURL.putAttribute(key, value);
            }
        });
        return systemURL;
    }

    /**
     * 注意一定要指定path，同时没有端口随机选择一个端口
     *
     * @param protocolConfig
     * @param systemConfigUrl
     * @return
     */
    public static URL buildUrlByProtocolConfig(ProtocolConfig protocolConfig, URL systemConfigUrl) {
        URL protocolUrl = new URL(systemConfigUrl);
        protocolUrl.setSystem_first(false);
        protocolUrl.setSide(PROVIDER);
        protocolUrl.setProtocol(protocolConfig.getName());
        protocolUrl.setPort(protocolConfig.getPort());
        return protocolUrl;
    }

    public static URL appMetaData2Url(AppMetaData appMetaData, URL protocolUrl) {
        String protocolName = protocolUrl.getProtocol();
        URL subUrl = new URL(protocolUrl);
        subUrl.setSystem_first(false);
        subUrl.setHost(appMetaData.getIp());
        ProtocolMetadata protocolMetadata = appMetaData.getProtocols().get(protocolName);
        if (protocolMetadata != null) {
            subUrl.setPort(protocolMetadata.getPort());
        } else {
            subUrl.setPort(protocolUrl.getPort());
        }
        return subUrl;
    }
}
